package mgo

import (
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/mongo/options"
	"time"
)

type OptionInfo struct {
	Field   []string // 指定查询字段
	Sort    []string // 排序字段，如：[]string{"age","-time"}，按照 age 正向排序，当 age 相同时按照 time 逆向排序
	Limit   int64    // 查询数量，默认 10
	Page    int64    // 查询页数（实际使用的是 Skip 方法）
	Skip    int64    // 查询指定条件下跳过指定的数量（尽量不使用，性能差）
	MaxTime int64    // 查询最大等待时间
	// 预处理前置信息
	projection bson.D
	sort       bson.D
	limit      int64
	skip       int64
	maxTime    time.Duration
}

func (o *OptionInfo) buildOption() {
	// 1. 判断是否存在查询字段指定
	if len(o.Field) != 0 {
		var d bson.D
		for _, v := range o.Field {
			d = append(d, bson.E{v, 1})
		}
		o.projection = d
	}
	// 3. 判断是否存在排序字段
	if len(o.Sort) != 0 {
		var s bson.D
		for _, v := range o.Sort {
			if v[0:1] == "-" {
				s = append(s, bson.E{v[1:len(v)], -1})
			} else {
				s = append(s, bson.E{v, 1})
			}
		}
		o.sort = s
	}
	// 4.判断是否存在搜索数量限制，不存在则设置默认限制 10 条
	if o.Limit != 0 {
		o.limit = o.Limit
	} else {
		o.limit = 10
	}
	// 5. 判读是否存在分页或跳过查询设置
	if o.Skip != 0 {
		o.skip = o.Skip
	} else if o.Page != 0 {
		o.skip = o.Limit * (o.Page - 1)
	}
	// 6. 判断是否存在超时时间
	if o.MaxTime != 0 {
		o.maxTime = time.Duration(o.MaxTime) * time.Second
	}
}

// BuildFindOptions 构造 Find 查询 Option
func (o *OptionInfo) BuildFindOptions() *options.FindOptions {
	o.buildOption()
	return options.Find().SetProjection(o.projection).SetSort(o.sort).SetSkip(o.skip).SetLimit(o.limit).SetMaxTime(o.maxTime)
}

// BuildFindOneOptions 构造 FindOne 查询 Option
func (o *OptionInfo) BuildFindOneOptions() *options.FindOneOptions {
	o.buildOption()
	return options.FindOne().SetProjection(o.projection).SetSort(o.sort).SetSkip(o.skip).SetMaxTime(o.maxTime)
}

// BuildFindOneAndUpdateOptions 构造 FindOneAndUpdate 查询 Option
func (o *OptionInfo) BuildFindOneAndUpdateOptions() *options.FindOneAndUpdateOptions {
	o.buildOption()
	return options.FindOneAndUpdate().SetProjection(o.projection).SetSort(o.sort).SetMaxTime(o.maxTime)
}

// BuildFindOneAndDeleteOptions 构造 FindOneAndDelete 查询 Option
func (o *OptionInfo) BuildFindOneAndDeleteOptions() *options.FindOneAndDeleteOptions {
	o.buildOption()
	return options.FindOneAndDelete().SetProjection(o.projection).SetSort(o.sort).SetMaxTime(o.maxTime)
}

// BuildFindOneAndReplaceOptions 构造 FindOneAndReplace 查询 Option
func (o *OptionInfo) BuildFindOneAndReplaceOptions() *options.FindOneAndReplaceOptions {
	o.buildOption()
	return options.FindOneAndReplace().SetProjection(o.projection).SetSort(o.sort).SetMaxTime(o.maxTime)
}

// BuildDistinctOptions 构造 Distinct 查询 Option
func (o *OptionInfo) BuildDistinctOptions() *options.DistinctOptions {
	o.buildOption()
	return options.Distinct().SetMaxTime(o.maxTime)
}
